package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"net/http"
	"strings"
)

func getIPSwitch(cfg GetIPConfig) (string, error) {
	switch cfg.SwithMode {
	case GETIPMODE_PUBLIC_URL:
		log.Println("get ip from url")
		return getUrlIP(cfg.PublicUrl.Url)
	case GETIPMODE_CDMA:
		log.Println("get ip from cdma")
		return getIPFromCDMAMode(cfg.Cdma.Url, cfg.Cdma.Username, cfg.Cdma.Password)
	case GETIPMODE_ETHERNET:
		log.Println("get ip from ethernet")
		return getEthernetIP(cfg.Ethernet.Device, 1)
	default:
		log.Println("not support mode")
	}
	return "", errors.New("not support mode")
}

func getIPFromCDMAMode(url, username, password string) (string, error) {
	var loginURL = url + "?username=" + username + "&psd=" + password
	client := &http.Client{
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		},
	}
	resp, err := client.Get(loginURL)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	cookies := resp.Cookies()
	geturl := url + "/admin/settings/gwinfo?get=all"
	req, err := http.NewRequest("GET", geturl, nil)
	if err != nil {
		log.Printf("创建请求时发生错误:%v", err)
		return "", err
	}
	for _, cookie := range cookies {
		req.AddCookie(cookie)
	}

	// 发送请求并获取响应
	resp, err = client.Do(req)
	if err != nil {
		log.Printf("发送请求时发生错误:%v", err)
		return "", err
	}
	defer resp.Body.Close()
	b, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Printf("读取响应时发生错误:%v", err)
		return "", err
	}
	var jdata interface{}
	json.Unmarshal(b, &jdata)
	if jdata != nil {
		result := jdata.(map[string]interface{})
		if result["WANIP"] != nil {
			return result["WANIP"].(string), nil
		}
		log.Printf("获取WANIP失败:%v", jdata)
	}
	log.Printf("获取路由信息失败:%v", resp)
	return "", errNoIp
}

func getUrlIP(url string) (string, error) {
	response, err := http.Get(url)
	if err != nil {
		return "", err
	}
	defer response.Body.Close()

	body, err := io.ReadAll(response.Body)
	if err != nil {
		return "", err
	}

	ipString := strings.ReplaceAll(strings.ReplaceAll(string(body), " ", ""), "\n", "")
	log.Println("response body is ", ipString)
	ipAddress := net.ParseIP(ipString)
	if ipAddress != nil {
		return ipAddress.String(), nil
	}

	return "", errors.New("failed to parse IP address")
}

func getEthernetIP(interfaceName string, num int) (string, error) {
	interfaces, err := net.Interfaces()
	if err != nil {
		return "", err
	}

	var ips []string
	for _, iface := range interfaces {
		log.Println("found a interface, the name is ", iface.Name)
		if iface.Name == interfaceName {
			addrs, err := iface.Addrs()
			if err != nil {
				return "", err
			}

			for _, addr := range addrs {
				var ip net.IP
				switch v := addr.(type) {
				case *net.IPNet:
					ip = v.IP
				case *net.IPAddr:
					ip = v.IP
				}

				if ip != nil && !ip.IsLoopback() && ip.To4() != nil {
					ips = append(ips, ip.String())
				}
			}
			if num > len(ips) {
				return "", fmt.Errorf("未找到指定网卡: %s", interfaceName)
			}
			return ips[num-1], nil
		}
	}

	return "", fmt.Errorf("未找到指定网卡: %s", interfaceName)
}
